home *** CD-ROM | disk | FTP | other *** search
- PAGE 76,132
- TITLE VDISK-H.ASM Installable Device Driver for Vdisk in High Memory
-
- ;*************************************************************************
- ; AN INSTALLABLE DEVICE DRIVER TO CREATE A RAM DISK IN MEMORY ABOVE DOS, *
- ; OCCUPYING PAGES C and D (128K capacity). *
- ; by J. D. Kronman, based on the IBM example *
- ; driver in the PC-DOS technical reference manual *
- ; last revision 11/15/85 *
- ;*************************************************************************
-
- ; This driver differs from the IBM driver because it utilizes memory outside
- ; of the range normally used by DOS. You can take advantage of this if
- ; you DON'T have an XT that has ROM code for the controller in Page C, etc.
- ; and you could even make the VDISK 192K if pages C, D, and E are all free.
- ; I am using a MicroLog Baby Blue Plus and chose to keep Page E free for the
- ; Z-80. The following modifications were made to the original IBM driver:
- ;
- ; 1. The INIT routine was completely rewritten; it was also relocated so
- ; that the memory it occupies is released after INIT has completed its task.
- ; 2. A signon message was added.
- ; 3. Three new "dummy" entries were added to the function table for
- ; DOS 3.x compatibility.
- ; 4. The "unimplemented functions" now just exit; in the original version,
- ; they caused the read code to be executed.
- ;
- ; I am fairly new to the world of DOS drivers, so if I made any mistakes,
- ; I would appreciate hearing from you. I might code again and everyone will
- ; benefit if I am making only new mistakes!
- ;
- ; Jim Kronman
- ; Bacchus Data Services
- ; 6085 Venice Blvd., No. 16
- ; Los Angeles, CA 90034 (213) 558-3281
- ; CompuServe 76703,431
- ;
- ;--------------------------
-
- CSEG SEGMENT PARA PUBLIC 'CODE'
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; MACRO FOR STATUS
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- STATUS MACRO STATE,ERR,RC
- IFIDN <STATE>,<DONE>
- OR ES:WORD PTR SRH_STA_FLD[BX],0100H
- ENDIF
- IFIDN <STATE>,<BUSY>
- OR ES:WORD PTR SRH_STA_FLD[BX],0200H
- ENDIF
- IFIDN <ERR>,<ERROR>
- OR ES:WORD PTR SRH_STA_FLD[BX],1000H
- ENDIF
- IFNB <RC>
- OR ES:WORD PTR SRH_STA_FLD[BX],RC
- ENDIF
- ENDM
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; EQUATES
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- CR equ 0Dh
- LF equ 0Ah
-
- ; READ/WRITE
-
- SRH EQU 0 ;Static request header start
- SRH_LEN EQU 13 ; " " " length
- SRH_LEN_FLD EQU SRH ; " " " " field
- SRH_UCD_FLD EQU SRH+1 ; " " " Unit code
- SRH_CCD_FLD EQU SRH+2 ; " " " command code fld
- SRH_STA_FLD EQU SRH+3 ; " " " status field
- SRH_RES_FLD EQU SRH+5 ; " " "reserved area field
-
- MD EQU SRH+SRH_LEN ;Media description byte
- MD_LEN EQU 1 ; " " " length
- DTA EQU MD+MD_LEN ;disk transfer address
- DTA_LEN EQU 4 ;dta length
- COUNT EQU DTA+DTA_LEN ;byte/sector count
- COUNT_LEN EQU 2 ; " " " length
- SSN EQU COUNT+COUNT_LEN ;starting sector number
- SSN_LEN EQU 2 ; " " " length
-
- ; MEDIA CHECK
-
- RET_BYTE EQU MD+MD_LEN ;byte returned from driver
-
- ; BUILD B(ios) P(arameter) B(lock)
-
- BPBA_PTR EQU DTA+DTA_LEN ;Pointer to BPB
- BPBA_PTR_LEN EQU 4 ; " " " length
-
- ; INIT
-
- UNITS EQU SRH+SRH_LEN
- UNITS_LEN EQU 1
- BR_ADDR_0 EQU UNITS+UNITS_LEN
- BR_ADDR_1 EQU BR_ADDR_0+2
- BR_ADDR_LEN EQU 4
- BPB_PTR_OFF EQU BR_ADDR_0+BR_ADDR_LEN
- BPB_PTR_SEG EQU BPB_PTR_OFF+2
-
- ;============== C O D E B E G I N S H E R E ================
-
- VDSK PROC FAR ;Start Virtual disk procedure
- ASSUME CS:CSEG,ES:CSEG,DS:CSEG
-
- BEGIN:
- START EQU $
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; DEVICE HEADER
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- NEXT_DEV DD -1 ;Pointer to next device
- ATTRIBUTE DW 2000H ;Block device(non-IBM format)
- STRATEGY DW DEV_STRATEGY ;pointer to DeviceStrategy
- INTERRUPT DW DEV_INT ;pointer to device interrupt handler
- DEV_NAME DB 1 ;Number of block devices
- DB 7 DUP(?) ;7 Bytes of filler
-
- RH_OFF DW ? ;Request Header offset
- RH_SEG DW ? ;Request Header segment
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; BIOS PARAMETER BLOCK
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- BPB equ $
- dw 512 ;Sector size
- db 1 ;Sectors/allocation unit
- dw 1 ;Number of reserved sectors
- db 2 ;Number of FATS
- dw 64 ;Number of directory entries
- dw 256 ;Total sectors (128kb * 2 sec/kb)
- db 0FCh ;Media descriptor (like 1 side 9 spt)
- dw 2 ;No.sectors occupied by FAT
-
- BPB_PTR dw BPB ;BPB pointer array (1 entry)
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; VARIABLES
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- TOTAL DW ? ;Total sectors to transfer
- VERIFY DB 0 ;Verify 1=Yes, 0 = No
- START_SEC DW 0 ;Starting sector number
- VDISK_PTR DW 0C000h ;Starting segment of virtual disk
- USER_DTA DD ? ;Ptr to callers disk transfer address
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; FUNCTION TABLE
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- FUNTAB LABEL BYTE
- DW INIT ;initialization
- DW MEDIA_CHECK ;Media check ( block only)
- DW BUILD_BPB ;Build BPB ( block only)
- DW IOCTL_IN ;IOCTL input
- DW INPUT ;Input(read)
- DW NO_INPUT ;non/dest.input,no wait(chr only)
- DW IN_STAT ;Input status
- DW IN_FLUSH ;Input flush
- DW OUTPUT ;Output(write)
- DW OUT_VERIFY ;Output(write)with verify
- DW OUT_STAT ;Output status
- DW OUT_FLUSH ;Output flush
- DW IOCTL_OUT ;IOCTL output
- dw DOS3 ;DOS3 uses this
- dw DOS3 ;DOS3 uses this
- dw DOS3 ;DOS3 uses this
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; LOCAL PROCEDURES
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- IN_SAVE PROC NEAR
- MOV AX,ES:WORD PTR DTA[BX] ;Save callers DTA
- MOV WORD PTR CS:USER_DTA,AX
- MOV AX,ES:WORD PTR DTA+2[BX]
- MOV WORD PTR CS:USER_DTA+2,AX
- MOV AX,ES:WORD PTR COUNT[BX];get number of sectors to read
- XOR AH,AH
- MOV CS:TOTAL,AX ;move number of sectors to total
- RET
- IN_SAVE ENDP
-
- CALC_ADDR PROC NEAR
- MOV AX,CS:START_SEC ;Get starting sector number
- MOV CX,20H ;move 512 to cx segment style
- MUL CX ;multiply to get actual sector
- MOV DX,CS:VDISK_PTR ;get segment of virtual disk
- ADD DX,AX ;add that segment to initial segment
- MOV DS,DX ;save that as actual segment
- XOR SI,SI ;its on paragraph boundary
- MOV AX,CS:TOTAL ;total number of sectors to read
- MOV CX,512 ;bytes per sector
- MUL CX ;multiply to get copy length
- OR AX,AX ;check for greater than 64k
- JNZ MOVE_IT
- MOV AX,0FFFFH ;move in for 64k
- MOVE_IT:
- XCHG CX,AX ;move length to cx
- RET
- CALC_ADDR ENDP
-
- SECTOR_READ PROC NEAR
- CALL CALC_ADDR ;calculate starting"sector"
- MOV ES,WORD PTR CS:USER_DTA+2 ;set destination)ES:DI)to point
- MOV DI,WORD PTR CS:USER_DTA ; to callers dta
-
- ; CHECK FOR DTA WRAP IN CASE WE CAME THROUGH VIA VERIFY
-
- MOV AX,DI ;get offset of dta
- ADD AX,CX ;add copy length to it
- JNC READ_COPY ;carry flag=0,no wrap
- MOV AX,0FFFFH ;maximum length
- SUB AX,DI ;subtract dta offset from max
- MOV CX,AX ;issue that as copy length to not wrap
-
- READ_COPY:
- REP MOVSB ;do the "read"
- RET
- SECTOR_READ ENDP
-
- SECTOR_WRITE PROC NEAR
- CALL CALC_ADDR ;Calculate starting sector
- PUSH DS
- POP ES ;Establish addressability
- MOV DI,SI ;ES:DI point to disk
- MOV DS,WORD PTR CS:USER_DTA+2 ;DS:DI point to callers dta
- MOV SI,WORD PTR CS:USER_DTA
-
- ; CHECK FOR DTA WRAP
-
- MOV AX,SI ;Move dta offset to ax
- ADD AX,CX ;add copy length to offset
- JNC WRITE_COPY ;carry flag=0,no segment wrap
- MOV AX,0FFFFH ;move in max copy length
- SUB AX,SI ;subtract dta offset from max
- MOV CX,AX ;use as new copy length to avoid wrap
-
- WRITE_COPY:
- REP MOVSB ;do the write
- RET
- SECTOR_WRITE ENDP
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; DEVICE STRATEGY
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- DEV_STRATEGY:
- mov CS:RH_SEG,ES ;save segment of request header ptr
- mov CS:RH_OFF,BX ;save offset of " " "
- ret
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; DEVICE INTERRUPT HANDLER
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- DEV_INT:
-
- CLD ;PRESERVE MACHINE STATE ON ENTRY
- PUSH DS
- PUSH ES
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH DI
- PUSH SI
-
- ; DO THE BRANCH ACCORDING TO THE FUNCTION PASSED
-
- MOV AL,ES:[BX]+2 ;Get function byte
- ROL AL,1 ;Get offset into table
- LEA DI,FUNTAB ;get address funtab
- XOR AH,AH
- ADD DI,AX
- JMP WORD PTR[DI]
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; MEDIA CHECK
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- MEDIA_CHECK: ;Media check (block only) - set media not changed
- MOV ES:BYTE PTR RET_BYTE[BX],1 ;store in return byte
- STATUS DONE,NOERROR,0 ;turn on done bit (macro)
- JMP EXIT
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; BUILD BIOS PARAMETER BLOCK
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- BUILD_BPB:
- PUSH ES ;save srh segment
- PUSH BX ;save rh_offset
- MOV CS:WORD PTR START_SEC,0
- MOV CS:WORD PTR TOTAL,1
- CALL CALC_ADDR ;calculate address of first sector
- PUSH CS
- POP ES
- LEA DI,WORD PTR BPB ;address of BIOS paramter block
- ADD SI,11 ;add 11 to si
- MOV CX,13 ;length of bpb
- REP MOVSB
- POP BX ;restore offset of srh
- POP ES ;restore segment of srh
- LEA DX,WORD PTR BPB ;get BPB array pointer
- MOV ES:BPBA_PTR[BX],DX ;save pointer to BPB table
- MOV ES:BPBA_PTR+2[BX],CS
- MOV ES:DTA[BX],DX ;offset of sector buffer
- MOV ES:DTA+2[BX],CS
- STATUS DONE,NOERROR,0 ;set status (macro)
- JMP EXIT
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; DISK READ
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- INPUT:
- CALL IN_SAVE ;call initial save routine
- MOV AX,ES:WORD PTR SSN[BX] ;get starting sector number
- MOV CS:START_SEC,AX ;save starting sector number
- MOV AX,ES:WORD PTR COUNT[BX]
- MOV CS:TOTAL,AX ;save total sectors to transfer
- CALL SECTOR_READ ;readin that many sectors
- MOV BX,CS:RH_OFF ;restore ES:BX as request hdr ptr
- MOV ES,CS:RH_SEG
- STATUS DONE,NOERROR,0
- JMP EXIT
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; DISK WRITE
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- OUTPUT: ;output(write)
- CALL IN_SAVE
- MOV AX,ES:WORD PTR SSN[BX] ;get starting sector number
- MOV CS:START_SEC,AX ;set " " "
- MOV AX,ES:WORD PTR COUNT[BX]
- MOV CS:TOTAL,AX ;save total sectors to write
- CALL SECTOR_WRITE ;write out those sectors
- MOV BX,CS:RH_OFF ;restore ES:BX as request hdr ptr
- MOV ES,CS:RH_SEG
- CMP CS:BYTE PTR VERIFY,0 ;write verify set
- JZ NO_VERIFY ;no, no write verify
- MOV CS:BYTE PTR VERIFY,0 ;reset verify indicator
- JMP INPUT
- NO_VERIFY:
- STATUS DONE,NOERROR,0 ;set done,noerror in statusword
- JMP EXIT
- OUT_VERIFY: ;output(write)with verify
- MOV CS:BYTE PTR VERIFY,1 ;set the verify flag
- JMP OUTPUT ;branch to output routine
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; NOT SUPPORTED BY THIS DEVICE
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- IOCTL_IN:
- IOCTL_OUT:
- NO_INPUT:
- IN_STAT:
- IN_FLUSH:
- OUT_STAT:
- OUT_FLUSH:
- DOS3: ;fall thru to exit (does nothing)
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; COMMON EXIT
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- EXIT:
- POP SI ;restore all registers
- POP DI
- POP DX
- POP CX
- POP BX
- POP AX
- POP ES
- POP DS
- RET
-
- END_OF_DRIVER equ $ ;the end of the code that must remain
- ;what follows is used once and discarded
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; INITIALIZE DRIVER
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- INIT:
- mov AX,OFFSET CS:EXIT ;kill init table entry
- mov WORD PTR CS:[FUNTAB],AX ; (just for safety)
-
- push DX
- mov DX,OFFSET CS:SIGNON ;
- mov AH,9 ;
- int 21h ;tell user we're here
- pop DX
-
- mov AX,OFFSET CS:END_OF_DRIVER ;get the end of this driver code
- mov ES:BR_ADDR_0[BX],AX ;break address (offset) is the end
- mov ES:WORD PTR BR_ADDR_1[BX],CS ;code segment for break address
- mov ES:BYTE PTR UNITS[BX],1 ;number of units
- lea DX,WORD PTR BPB_PTR ;address of bpb pointer array
- mov ES:BPB_PTR_OFF[BX],DX ;save offset in data packet
- mov ES:BPB_PTR_SEG[BX],CS ;save segment in data packet
-
- mov ES,CS:VDISK_PTR ;get start segment of virtual disk
- xor DI,DI ;DI=0 (boot sector)
- push CS
- pop DS ;source seg is CS
- lea SI,WORD PTR CS:BOOT_REC ;address of boot record
- mov CX,11
- rep movsb ;copy first part of boot record
- lea SI,WORD PTR CS:BPB ;get rest of boot record from BPB
- mov CX,13 ;
- rep movsb ;24 bytes, in all
-
- mov ES,CS:VDISK_PTR ;sector for disk
- mov DI,200h ;second sector of disk
- mov CX,400h ;two sectors
- xor AL,AL ;move in nulls
- rep stosb ;zero out FAT area
-
- mov DS,CS:VDISK_PTR ;segment for VDISK
- mov ES,CS:VDISK_PTR ;
- mov SI,200h ;second sector (01) is source
- mov DI,600h ;4th sector (03) is destination
- mov DS:BYTE PTR [SI],0FCH ;set first FAT entry
- mov DS:BYTE PTR 1[SI],0FFH
- mov DS:BYTE PTR 2[SI],0FFH
- mov CX,400h ;2 sectors per fat
- rep movsb ;copy first FAT to second FAT
-
- push CS ;
- pop DS ;restore DS for print function
-
- mov ES,CS:VDISK_PTR ;VDISK segment
- mov DI,0A00h ;start 6th sector (05)
- mov CX,800h ;4 sectors in directory
- xor AL,AL ;null byte for fill
- rep stosb ;zero out directory
-
- mov ES,CS:RH_SEG ;restore ES:BX to request header
- mov BX,CS:RH_OFF
- STATUS DONE,NOERROR,0 ;set status word (Macro)
-
- push DX
- mov DX, OFFSET CS:TELL5
- mov AH,9
- int 21h
- pop DX ;VDISK installation complete
-
- jmp EXIT
-
- BOOT_REC EQU $ ;Dummy DOS boot record
- db 3 DUP(0) ;3 Byte jump to boot code (null here)
- db 8 dup (' ') ;Vendor ID (must be 8 bytes)
- ;the rest of the boot record is the same as the BPB
-
- SIGNON:
- db CR,LF,'128K Ram Disk in High Memory Pages C and D.'
- db CR,LF,'By J. D. Kronman -- 15 November 1985'
- db CR,LF
- db '$'
- TELL5:
- db CR,LF,'VDISK-H installed.'
- db CR,LF
- db '$'
-
- VDSK endp
- CSEG ends
- end BEGIN